import numpy as np
from metrics import r2_score
class SimpleLinearRegression1:
    def __init__(self):
        self.a_=None
        self.b_=None
    def fit(self,x_train,y_train):
        assert x_train.ndim==1#训练集输入是1维
        assert len(x_train)==len(y_train)#x与y训练集长度相同（对应）

        x_mean=np.mean(x_train)
        y_mean=np.mean(y_train)
        num=0.0#求a分子
        d=0.0#求a分母
        for x_i,y_i in zip(x_train,y_train):
            num=num+(x_i-x_mean)*(y_i-y_mean)#a分子累加求和
            d=d+(x_i-x_mean)**2#a分母累加求和

        self.a_=num/d#求出参数a
        self.b_=y_mean-self.a_*x_mean#求出参数b
        return self
    def predict(self,x_predict):
        """给定预测数据集x_predict"""
        assert x_predict.ndim==1
        assert self.a_ is not None and self.b_ is not None#必须训练后才能预测
        return np.array([self._predict(x) for x in x_predict])
    
    def _predict(self,x_single):#x_single是一个属
        return self.a_*x_single+self.b_
    
    def __repr__(self):
        return "简单线性回归"


class SimpleLinearRegression2:
    def __init__(self):
        self.a_=None
        self.b_=None
    def fit(self,x_train,y_train):
        assert x_train.ndim==1#训练集输入是1维
        assert len(x_train)==len(y_train)#x与y训练集长度相同（对应）

        x_mean=np.mean(x_train)
        y_mean=np.mean(y_train)
        num=0.0#求a分子
        d=0.0#求a分母
        """向量化计算=>提速"""
        num=(x_train-x_mean).dot(y_train-y_mean)#分子向量化计算（点乘）
        d=(x_train-x_mean).dot(x_train-x_mean)#分子向量化计算（点乘）
        self.a_=num/d#求出参数a
        self.b_=y_mean-self.a_*x_mean#求出参数b
        return self
    def predict(self,x_predict):
        """给定预测数据集x_predict"""
        assert x_predict.ndim==1
        assert self.a_ is not None and self.b_ is not None#必须训练后才能预测
        return np.array([self._predict(x) for x in x_predict])

    def score(self,x_test,y_test):
        y_predict=self.predict(x_test)
        return r2_score(y_test,y_predict)

    def _predict(self,x_single):#x_single是一个属
        return self.a_*x_single+self.b_
        
    def __repr__(self):
        return "简单线性回归"       


